#include "widget.h"
#include "ui_widget.h"
#include <QPalette>
#include <QPixmap>
#include <QDesktopServices>

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    this->setWindowFlags(Qt::FramelessWindowHint | Qt::WindowSystemMenuHint | Qt::WindowMinimizeButtonHint);
    ui->setupUi(this);
    ui->L_speed->setText(QString("速度:")+QString::number(ui->HS_speed->value()));
    QPalette inputData_pl = ui->inputData->palette();
    inputData_pl.setBrush(QPalette::Base,QBrush(QColor(255,255,255,50)));

    ui->inputData->setPalette(inputData_pl);

    QPalette outputData_pl = ui->outputData->palette();
    outputData_pl.setBrush(QPalette::Base,QBrush(QColor(255,255,255,50)));
    ui->outputData->setPalette(outputData_pl);

    this->setAutoFillBackground(true);
    QPalette palette;
    QPixmap pixmap(":/background/pic/back7.jpg");
    palette.setBrush(QPalette::Window, QBrush(pixmap));
    this->setPalette(palette);



    for(int i=0;i<9;++i){
        for(int j=0;j<9;++j){
            mpValue[i][j]='0';
            mpColor[i][j]=QColor(0,0,0,255);
            bgColor[i][j]=QColor(255,102,0,0);
        }
    }
}

void Widget::init(){
    /*
     * 重置所有数据。
    */
    for(int i=0;i<9;++i){
        for(int j=0;j<9;++j){
            mpValue[i][j]='0';
            mpColor[i][j]=QColor(0,0,0,255);
            bgColor[i][j]=QColor(255,102,0,0);
            mp[i][j]=0;
            row[i][j]=false;
            col[i][j]=false;
            grid[i][j]=false;
        }
    }
}


void Widget::paintEvent(QPaintEvent*)

{
    paint=new QPainter;
    paint->begin(this);
    paint->setPen(QPen(Qt::blue,4,Qt::SolidLine));

//    paint->setBrush(QBrush(Qt::,Qt::SolidPattern));
//    paint->drawRect(QRect(QPoint(0,0),QSize(450,450)));

    // 画框


    // 画背景
    paint->setPen(QPen(QColor(75,0,130,0),0,Qt::SolidLine));
    for(int i=0;i<9;++i){
        for(int j=0;j<9;j++){
            paint->setBrush(QBrush(bgColor[i][j]));
            paint->drawRect(QRect(QPoint(i*50+tmpx,j*50+tmpy),QSize(50,50)));
        }
    }

    paint->setPen(QPen(Qt::darkGreen,2,Qt::SolidLine));
    for(int i=0;i<=450;i+=50){
        if(i%150){
            paint->drawLine(QPoint(i+tmpx,0+tmpy),QPoint(i+tmpx,450+tmpy));
            paint->drawLine(QPoint(0+tmpx,i+tmpy),QPoint(450+tmpx,i+tmpy));
        }
    }

    paint->setPen(QPen(QColor(75,0,130),4,Qt::SolidLine));
    for(int i=0;i<=450;i+=150){
 //           paint->setPen(QPen(Qt::darkGreen,2,Qt::SolidLine));
            paint->drawLine(QPoint(i+tmpx,0+tmpy),QPoint(i+tmpx,450+tmpy));
            paint->drawLine(QPoint(0+tmpx,i+tmpy),QPoint(450+tmpx,i+tmpy));
    }



    //画数字
    paint->setFont(QFont("等线 Light",30,QFont::Bold));
    //paint->setPen(QPen(Qt::blue,10,Qt::SolidLine));
    for(int i=0;i<9;i++){
        for(int j=0;j<9;j++)
            if(mpValue[i][j]!=QString('0')){
      //          mpColor[j][i] = Qt::black;
                paint->setPen(mpColor[i][j]);
                paint->drawText(QPoint(15+tmpx+j*50,40+tmpy+i*50),mpValue[i][j]);
            }
    }

    paint->end();
}
Widget::~Widget()
{
    delete ui;
}

bool Widget::checkSudoku(){
    bool tmpTest[10];
    for(int i=0;i<9;++i){
        memset(tmpTest,false,sizeof(tmpTest));
        for(int j=0;j<9;++j){
            int value = mp[i][j];
            if(value>0 && tmpTest[value]){
                delete[] tmpTest;
                return false;
            }
            else tmpTest[value]=true;
        }
    }
    for(int i=0;i<9;++i){
        memset(tmpTest,false,sizeof(tmpTest));
        for(int j=0;j<9;++j){
            int value = mp[j][i];
            if(value>0 && tmpTest[value])
            {
                delete[] tmpTest;
                return false;
            }
            else tmpTest[value]=true;
        }
    }
    for(int i=0;i<9;++i){
        memset(tmpTest,0,sizeof(tmpTest));
        for(int j=0;j<9;j++){
            int value = mp[(i/3)*3+j/3][(i%3)*3+j%3];
            if(value>0 && tmpTest[value])
            {
                delete[] tmpTest;
                return false;
            }
            else tmpTest[value]=true;
        }
    }
    delete[] tmpTest;
    return true;
}

void Widget::on_inputData_textChanged()
{
    for(int i=0;i<9;++i){
        for(int j=0;j<9;++j){
            mpValue[i][j]='0';
            mpColor[i][j]=Qt::black;
        }
    }
    updatePane();
}


void Widget::solve(){
    memset(row,false,sizeof row);
    memset(col,false,sizeof col);
    memset(grid,false,sizeof grid);

    for(int i=0;i<9;++i){
        for(int j=0;j<9;++j){
            if(mp[i][j]){
                int k = 3*(i/3)+j/3;
                row[i][mp[i][j]-1] = true;
                col[j][mp[i][j]-1] = true;
                grid[k][mp[i][j]-1] = true;
                mpColor[i][j]=Qt::black;
            }
        }
    }
 //   debug();
    mydfs(0,0);
    init();
}



void Widget::updateThis(){
    QMessageBox::information(this,"Here","update",QMessageBox::YesAll);
}
void Widget::updatePane(){
    std::string inputStd = this->ui->inputData->toPlainText().toStdString();
    unsigned int x = 0;
    unsigned int y = 0;
    memset(tmpValue,0,sizeof(tmpValue));
    while(x<=81&&y<inputStd.length()){
        if(isdigit(inputStd[y])){
           tmpValue[x++]=inputStd[y]-'0';
        }else{
           tmpValue[x++]=0;
        }
        y++;
    }
    inputStd.~basic_string();
    for(int i=0;i<9;i++)
        for(int j=0;j<9;j++){
               mp[i][j] = tmpValue[i*9+j];
               mpValue[i][j]=tmpValue[i*9+j]+'0';
               if(mp[i][j]){
                   row[i][mp[i][j]-1]=true;
                   col[j][mp[i][j]-1]=true;
                   grid[3*(i/3)+j/3][mp[i][j]-1]=true;
               }
        }
    this->update();
}

void Widget::on_showStart_clicked()
{
    this->ui->outputData->clear();
    for(int i=0;i<9;++i){
        for(int j=0;j<9;++j){
            mpValue[i][j]='0';
            mpColor[i][j]=Qt::black;
        }
    }
    QString getS = this->ui->inputData->toPlainText();
    if(getS.isEmpty()){

     //   QMessageBox::information(this,"Title","empty");

        tmpSudoku = new CSudoku(ui->HS_space->value());
        for(int i=0;i<9;i++)
            for(int j=0;j<9;j++){
               mpValue[i][j] = tmpSudoku->getAtom(i,j)+'0';
               mp[i][j] = tmpSudoku->getAtom(i,j);
               if(mp[i][j]){
                   row[i][mp[i][j]-1]=true;
                   col[j][mp[i][j]-1]=true;
                   grid[3*(i/3)+j/3][mp[i][j]-1]=true;

               }
            }
        delete tmpSudoku;
        this->update();
    }
    else{
        updatePane();

        if(checkSudoku()){
         //   QMessageBox::information(this,"Title","YES",QMessageBox::Yes);

        }else{
            if(QMessageBox::warning(this,"输入不合法","是否要使用系统数据?",QMessageBox::Yes|QMessageBox::Cancel)==QMessageBox::Yes){
                tmpSudoku = new CSudoku(ui->HS_space->value());
                for(int i=0;i<9;i++)
                    for(int j=0;j<9;j++){
                       mpValue[i][j] = tmpSudoku->getAtom(i,j)+'0';
                       mp[i][j] = tmpSudoku->getAtom(i,j);
                       if(mp[i][j]){
                           row[i][mp[i][j]-1]=true;
                           col[j][mp[i][j]-1]=true;
                           grid[3*(i/3)+j/3][mp[i][j]-1]=true;
                       }
                    }
                delete tmpSudoku;
                this->update();
            }
        }
    }
    getS.~QString();
    ui->showStart->setEnabled(false);
    ui->inputData->setEnabled(false);
    solve();
    sleep(2500-ui->HS_speed->value()*10);
    if(ui->CB_continue->isChecked()){
        ui->inputData->clear();
        ui->showStart->clicked();
    }else{
        ui->showStart->setEnabled(true);
        ui->inputData->setEnabled(true);
    }
}
void Widget::debug(){
    for(int i=0;i<9;i++){
        for(int j=0;j<9;j++){
            std::cout << mp[i][j] << " ";
        }
        std::cout << std::endl;
    }
    for(int i=0;i<9;i++){
        for(int j=0;j<9;j++){
            std::cout << row[i][j] << " ";
        }
        std::cout << std::endl;
    }
    for(int i=0;i<9;i++){
        for(int j=0;j<9;j++){
            std::cout << col[i][j] << " ";
        }
        std::cout << std::endl;
    }
    for(int i=0;i<9;i++){
        for(int j=0;j<9;j++){
            std::cout << grid[i][j] << " ";
        }
        std::cout << std::endl;
    }
}


void Widget::mousePressEvent(QMouseEvent *lpEvent)
{
 //   __super::mousePressEvent(lpEvent);
    if (lpEvent->button() == Qt::LeftButton)
    {
        m_WindowPos = this->pos();
        m_MousePos = lpEvent->globalPos();
        this->m_MousePressed = true;
    }
}

void Widget::mouseReleaseEvent(QMouseEvent *lpEvent)
{
   // __super::mouseReleaseEvent(lpEvent);
    if (lpEvent->button() == Qt::LeftButton)
    {
        this->m_MousePressed = false;
    }
}

void Widget::mouseMoveEvent(QMouseEvent *lpEvent)
{
    if (m_MousePressed)
    {
        this->move(m_WindowPos + (lpEvent->globalPos() - m_MousePos));
    }
}

void Widget::on_PB_exit_clicked()
{
    if(QMessageBox::warning(this,"Sudoku","确定退出?",QMessageBox::Yes|QMessageBox::No)==QMessageBox::Yes){
        exit(0);
    }
}

void Widget::on_PB_toMin_clicked()
{
    this->setWindowState(Qt::WindowMinimized);
}

bool Widget::mydfs(const int &x,const int &y){
    if(x==9) return true;
    bool flag = false;
    if(mp[x][y]){
        if(y==8) {
            flag = mydfs(x+1,0);
        }
        else {
            flag = mydfs(x,y+1);
        }
        if(flag) {
            return true;
        }
        else {
            return false;
        }
    }else{


        try_Point(x,y);
        this->ui->outputData->appendPlainText(QString("尝试解决点 (")+QString::number(x)+QString(",")+QString::number(y)+QString(")"));


        this->update();
        sleep(200-ui->HS_speed->value());
        int k = 3*(x/3) + y/3 ;

        for(int i=1;i<=9;i++){

            try_P_val(x,y,k);
    //        mp[x][y] = i;
            mpValue[x][y]=i+'0';
            this->ui->outputData->appendPlainText(QString("假设点 (")+QString::number(x)+QString(",")+QString::number(y)+QString(",")+QString::number(k)+QString(")的值为")+QString::number(i));
            mpValue[x][y]='0';
            this->update();
            sleep(200-ui->HS_speed->value());
            this->ui->outputData->appendPlainText(QString("取消假设 (")+QString::number(x)+QString(",")+QString::number(y)+QString(",")+QString::number(k)+QString(")"));
            cal_P_val(x,y,k);
            this->update();
            // 信号   (x,i) (y,i) (k,i)
            if(!row[x][i-1]&&!col[y][i-1]&&!grid[k][i-1]){
 //               std::cout << "now " << x << " " << y << " " << mp[x][y] << std::endl;
                mp[x][y] = i;
                mpValue[x][y]=i+'0';
                set_P_val(x,y);
                this->update();
                this->ui->outputData->appendPlainText(QString("暂时设置 (")+QString::number(x)+QString(",")+QString::number(y)+QString(",")+QString::number(k)+QString(")的值为")+QString::number(i));
                // 信号 临时设置(x,y,i)
                sleep(200-ui->HS_speed->value());

                row[x][i-1] = true;
                col[y][i-1] = true;
                grid[k][i-1] = true;
                if(y==8) {
                    flag = mydfs(x+1,0);
                }
                else {
                    flag = mydfs(x,y+1);
                }
                if(!flag){
                    del_P_val(x,y);
                    this->update();
                    mpValue[x][y]='0';
                    mp[x][y] = 0;
                    this->ui->outputData->appendPlainText(QString("取消设置 (")+QString::number(x)+QString(",")+QString::number(y)+QString(",")+QString::number(k)+QString(")的值为")+QString::number(i));
                    // 信号 取消 (x,y,i)
                    sleep(200-ui->HS_speed->value());

                    row[x][i-1] = false;
                    col[y][i-1] = false;
                    grid[k][i-1] = false;
                }else{
                    return true;
                }
            }
            mpValue[x][y]='0';
            mp[x][y]=0;
        }
    }
    return false;
}
void Widget::sleep(unsigned int msec) //延时器来自blog.fcsys.org
{
    QEventLoop eventloop;
    QTimer::singleShot(msec, &eventloop, SLOT(quit()));
    eventloop.exec();
}
void Widget::try_Point(int tx,int ty){
    mpColor[tx][ty]=Qt::red;
}
void Widget::try_P_val(int x,int y,int k){
    for(int i=0;i<9;++i){
        if(i!=y)
            bgColor[i][x]=QColor(255,102,0,200);
        if(i!=x)
            bgColor[y][i]=QColor(255,102,0,200);
    }
    for(int i=0;i<3;++i){
        for(int j=0;j<3;++j){
            if(j+k%3*3!=y||i+k/3*3!=x)
                bgColor[j+k%3*3][i+k/3*3]=QColor(255,102,0,200);
        }
    }
    bgColor[y][x]=QColor(204,102,0,200);
}
void Widget::cal_P_val(int x,int y,int k){
    for(int i=0;i<9;++i){
        bgColor[i][x]=QColor(255,102,0,0);
        bgColor[y][i]=QColor(255,102,0,0);
    }
    for(int i=0;i<3;++i){
        for(int j=0;j<3;++j){
            bgColor[j+k%3*3][i+k/3*3]=QColor(255,102,0,0);
        }
    }
}
void Widget::set_P_val(int x,int y){
    mpColor[x][y]=Qt::blue;
}
void Widget::del_P_val(int x,int y){
    mpColor[x][y]=Qt::black;
}

void Widget::on_L_ad_linkActivated(const QString &link)
{
    QDesktopServices::openUrl(QUrl(link));
}


void Widget::on_HS_speed_sliderMoved(int position)
{
    ui->L_speed->setText(QString("速度:")+QString::number(position));
}
